/*
 * Copyright 2009 Colin Prinn
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

package net.recursv.motific.at.runner;

import net.recursv.motific.at.command.AtCommand;
import net.recursv.motific.at.command.AtCommandManager;
import net.recursv.motific.utils.StringList;
import net.recursv.motific.utils.WrappedException;
import net.recursv.motific.utils.files.FileSystem;

import java.io.IOException;

/**
 * Created by: recursv
 * Date: 13/08/2009
 * Time: 2:56:48 PM
 */
public class ScriptBuilder {
    public ScriptIterator createIterator(String scriptDirectory) {
        try {
            return wrappedCreateIterator(scriptDirectory);
        } catch (Throwable e) {
            throw new WrappedException(e);
        }
    }

    private ScriptIterator wrappedCreateIterator(String scriptDirectory) throws IOException {
        ScriptIterator iterator = new ScriptIterator();
        StringList map = FileSystem.listFiles(scriptDirectory);

        for (int i = 0; i < map.size(); i++)
            iterator.addScript(parseScript(FileSystem.readString(map.elementAt(i)), map.elementAt(i)));

        return iterator;
    }

    private AtScript parseScript(String contents, String title) {
        AtScript atScript = new AtScript(title);
        StringBuffer buffer = new StringBuffer();

        boolean inBlock = false;
        boolean inComment = false;
        for (int index = 0, line = 0; index < contents.length(); index++) {
            char c = contents.charAt(index);
            if (c == '\n' && !inBlock) {
                String s = buffer.toString().trim();
                if (s.length() > 0)
                    atScript.addCommand(parseCommand(getCommandIdentifier(s), getCommandParams(s), ++line));
                buffer.delete(0, buffer.length());
                inComment = false;
            } else {
                if (c == '{')
                    inBlock = true;
                else if (c == '}')
                    inBlock = false;
                else if (c == '#')
                    inComment = true;

                if (!inComment)
                    buffer.append(c);
            }
        }

        return atScript;
    }

    private AtCommand parseCommand(String identifier, String params, int lineNumber) {
        AtCommand command = AtCommandManager.getCommand(identifier);
        command.parse(params);
        command.setLineNumber(lineNumber);
        return command;
    }

    String getCommandIdentifier(String commandLine) {
        int spaceIndex = commandLine.indexOf(' ');
        int bracketIndex = commandLine.indexOf('{');

        if (bracketIndex > 0 && (spaceIndex < 0 || bracketIndex < spaceIndex))
            return commandLine.substring(0, bracketIndex);
        else if (spaceIndex > 0)
            return commandLine.substring(0, spaceIndex);
        else
            return commandLine;
    }

    String getCommandParams(String commandLine) {
        int spaceIndex = commandLine.indexOf(' ');
        int bracketIndex = commandLine.indexOf('{');

        if (bracketIndex > 0 && (spaceIndex < 0 || bracketIndex < spaceIndex))
            return commandLine.substring(bracketIndex + 1, commandLine.lastIndexOf('}')).trim();
        else if (spaceIndex > 0) {
            String s = commandLine.substring(spaceIndex + 1).trim();
            if (s.startsWith("{") && s.endsWith("}"))
                s = s.substring(1, s.length() - 2).trim();
            return s;
        } else
            return "";
    }
}
